/**
 * Areas module
 */
app.areas = {
	// Freeze stage flag
	_freeze : false,
	// Current area ID
	_currentArea : '',
	// Current location object
	_currentLocation : null,
	// Current location DOM element
	_$currentLocation : null,
	// Array of current active location DOM elements
	_$currentActiveLocations : [],
	// Stage element
	_$stage : null,
	
	// Areas cache
	_areas : [],
	// Area types cache
	_areaTypes : [],
	
	/**
	 * Module initialization
	 */
	init : function() {
		var that = this;
		
		this._$stage = $('#areaStage');
		
		/**
		 * Bind a handler to 'keypress' event of document
		 */
		$(document).keypress(function(event) {
			var directions = {
				37 : 'left',
				38 : 'up',
				39 : 'right',
				40 : 'down'
			};
			
			// If stage is freezed then just quit
			if (that._freeze) {
				return false;
			}
			
			// Move the player on area map to the new location
			that.move(directions[event.keyCode]);
			
			// Prevent actual key pressing
			return false;
		});
		
		// Initialize areas
		this.initAreas();
		// Display default area
		this.displayArea();
	},
	
	/**
	 * Set current location
	 *
	 * @param posX Horizontal position for current area
	 * @param posY Vertical position
	 */
	setCurrentLocation : function(posX, posY) {
		var px = 0, py = 0, cell, type, sight = 1, area;
		
		area = this._areas[this._currentArea];
		
		if (this._$currentLocation) {
			$(this._$currentLocation).removeClass('current');
		}
		
		if (this._$currentActiveLocations && this._$currentActiveLocations.length) {
			for (var i = 0; i < this._$currentActiveLocations.length; i++) {
				$(this._$currentActiveLocations[i]).removeClass('active');
			}
		}
		
		this._currentLocation = area.map[posY][posX];
		this._$currentLocation = $('#area-' + this._currentArea + '-location-' + posX + '-' + posY).addClass('current');
		
		for (var x = -sight; x < sight + 1; x++) {
			for (var y = -sight; y < sight + 1; y++) {
				if ((Math.abs(x) + Math.abs(y)) <= sight) {
					var cellPos = {
						'x' : +posX + x,
						'y' : +posY + y
					};
					var location = area.map[cellPos.y] && this._areaTypes[area.map[cellPos.y][cellPos.x]];
					
					if (!location || location.obstacle) {
						continue;
					}
					
					this._$currentActiveLocations.push($('#area-' + this._currentArea + '-location-' + cellPos.x + '-' + cellPos.y).addClass('active'));
				}
			}
		}
	},
	
	/**
	 * Move player in given direction
	 * Triggers 'locationchange' event
	 *
	 * @param direction Direction value; can be 'left', 'up', 'right', 'down'
	 */
	move : function(direction) {
		var steps = {
			'left' : [-1, 0],
			'up' : [0, -1],
			'right' : [1, 0],
			'down' : [0, 1]
		};
		var coords = this._$currentLocation.attr('id').replace(/^.*location\-/, '').split('-');
		var step = steps[direction];
		var newCoords = [+coords[0] + step[0], +coords[1] + step[1]];
		var newLocationObject = $('#area-' + this._currentArea + '-location-' + newCoords[0] + '-' + newCoords[1]);
		var area = this._areas[this._currentArea];
		var newLocation = area && area.map && area.map[newCoords[1]] && this._areaTypes[area.map[newCoords[1]][newCoords[0]]];
		
		if (!newLocationObject.size() || !newLocation || newLocation.obstacle) {
			return false;
		}
		
		this.setCurrentLocation(newCoords[0], newCoords[1]);
		
		for (var id in area.ways) {
			if ((newCoords[0] + ':' + newCoords[1]) == area.ways[id].coords && area.ways[id].area) {
				this.displayArea(area.ways[id].area, area.ways[id].location);
			}
		}
		
		//this.checkEnemies(area, newLocation);
		
		$(app).trigger('locationchange', area, newLocation);
	},
	
	/**
	 * Initialize areas
	 * Create areas and add them to stage
	 */
	initAreas : function() {
		var that = this;
		
		$.each(this._areas, function(id, area) {
			var areaLayer = $('<div>').addClass('area').attr('id', 'area-' + id);
			
			for (var y = 0; y < area.map.length; y++) {
				for (var x = 0; x < area.map[y].length; x++) {
					var location = $('<div>').addClass('location').attr('id', 'area-' + id + '-location-' + x + '-' + y);
					location.addClass(area.map[y][x]);
					
					if (x == 0) {
						location.addClass('first');
					}
					
					if (x == area.map[y].length - 1) {
						location.addClass('last');
					}
					
					location.appendTo(areaLayer);
				}
			}
			
			for (var way in area.ways) {
				var selector = area.ways[way].coords.replace(/(\d+):(\d+)/, '#area-' + id + '-location-$1-$2');
				
				$(selector, areaLayer).addClass(way == 'start' ? 'start' : 'exit');
			}
			
			areaLayer.appendTo(that._$stage);
		});
	},
	
	/**
	 * Display given area
	 *
	 * @param id Area ID; if empty then default area will be used
	 * @param location Location to start from; if empty then 'start' location will be used
	 */
	displayArea : function(id, location) {
		var area, coords;
		
		id = id || this._currentArea || 'main';
		area = this._areas[id];
		location = (location && area.ways[location]) || area.ways.start;
		coords = location.coords.split(':');
		
		$('#area-' + this._currentArea).hide();
		this._currentArea = id;
		
		this.setCurrentLocation(coords[0], coords[1]);
		
		$('#area-' + id).show();
	},
	
	/**
	 * Freeze the stage
	 */
	freezeStage : function() {
		this._freeze = true;
	},
	
	/**
	 * Unfreeze the stage
	 */
	unfreezeStage : function() {
		this._freeze = false;
	}
};

/**
 * Data initialization
 */
(function() {
	var areas = {
		main : {
			ways : {
				start : {
					coords : '0:0'
				},
				left : {
					coords : '7:0',
					area : 'level1'
				},
				down : {
					coords : '7:4',
					area : 'level2'
				}
			},
			enemies : {
				50 : 'rat'
			},
			map : [
				['cell', 'cell', 'wall', 'cell', 'cell', 'wall', 'wall', 'cell'],
				['wall', 'cell', 'wall', 'wall', 'cell', 'wall', 'cell', 'cell'],
				['wall', 'cell', 'cell', 'cell', 'cell', 'cell', 'cell', 'wall'],
				['cell', 'cell', 'wall', 'cell', 'cell', 'wall', 'cell', 'wall'],
				['wall', 'cell', 'wall', 'cell', 'wall', 'wall', 'cell', 'cell']
			]
		},
		level1 : {
			ways : {
				start : {
					coords : '3:3',
					area : 'main',
					location : 'left'
				},
				exit : {
					coords : '0:0',
					area : 'main'
				}
			},
			enemies : {
				30 : 'rat'
			},
			map : [
				['cell', 'cell', 'cell', 'cell', 'cell', 'cell'],
				['wall', 'wall', 'wall', 'wall', 'wall', 'cell'],
				['wall', 'cell', 'cell', 'cell', 'wall', 'cell'],
				['wall', 'cell', 'wall', 'cell', 'wall', 'cell'],
				['wall', 'cell', 'wall', 'wall', 'wall', 'cell'],
				['wall', 'cell', 'cell', 'cell', 'cell', 'cell'],
				['wall', 'wall', 'wall', 'wall', 'wall', 'wall']
			]
		},
		level2 : {
			ways : {
				start : {
					coords : '3:3',
					area : 'main',
					location : 'down'
				},
				exit : {
					coords : '0:0',
					area : 'main'
				}
			},
			map : [
				['cell', 'cell', 'cell', 'cell', 'cell', 'cell'],
				['wall', 'wall', 'wall', 'wall', 'wall', 'cell'],
				['wall', 'cell', 'cell', 'cell', 'wall', 'cell'],
				['wall', 'cell', 'wall', 'cell', 'wall', 'cell'],
				['wall', 'cell', 'wall', 'wall', 'wall', 'cell'],
				['wall', 'cell', 'cell', 'cell', 'cell', 'cell'],
				['wall', 'wall', 'wall', 'wall', 'wall', 'wall']
			]
		}
	};
	
	var areaTypes = {
		'cell' : {},
		'wall' : {
			obstacle : true,
			breakable : false
		}
	};
	
	app.areas._areas = areas;
	app.areas._areaTypes = areaTypes;
})();